﻿using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
//using Gma.UserActivityMonitor;


namespace LanTalk
{
    public partial class Form1 : Form
    {
        static private string iniFile = "msgconfig.ini";
        static private int puerto = 9050;
        static private bool usahostname = false;
        static private bool usausername = true;
        static private string msg = " HOYJAN!";
        public bool isCtrl = false;
        public bool isAlt = false;

        public static bool IsLocalIpAddress(string host)
        {
            try
            { // get host IP addresses
                IPAddress[] hostIPs = Dns.GetHostAddresses(host);
                // get local IP addresses
                IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());

                // test if any host IP equals to any local IP or to localhost
                foreach (IPAddress hostIP in hostIPs)
                {
                    // is localhost
                    if (IPAddress.IsLoopback(hostIP)) return true;
                    // is local address
                    foreach (IPAddress localIP in localIPs)
                    {
                        if (hostIP.Equals(localIP)) return true;
                    }
                }
            }
            catch { }
            return false;
        }

        static private void getConfig()
        {
            /*
            try
            {
                Console.WriteLine("[DEBUG] Abriendo " + iniFile);
                StreamReader sr = new StreamReader(iniFile);
                String line;

                do
                {
                    line = sr.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                    if (line.StartsWith("#"))
                    {
                        // Console.WriteLine("[DEBUG] config: " + line);
                    }
                    if (line.StartsWith("Puerto"))
                    {
                        puerto = int.Parse(sr.ReadLine());
                        Console.WriteLine("[DEBUG] config: puerto: " + puerto);
                    }
                    if (line.StartsWith("UsaHostname"))
                    {
                        usahostname = true;
                        Console.WriteLine("[DEBUG] config: hostname habilitado");
                    }
                    if (line.StartsWith("UsaUsername"))
                    {
                        usausername = false;
                        Console.WriteLine("[DEBUG] config: username deshabilitado");
                    }
                    if (line.StartsWith("Mensaje"))
                    {
                        msg = sr.ReadLine();
                        Console.WriteLine("[DEBUG] config: mensaje: " + line);
                    }
                }

                while (line != null);
                sr.Close();
            }
            catch (Exception e)
            {

                Console.WriteLine("[DEBUG] No se encontró o hubo un problema abriendo " + iniFile + " Excepción: " + e.ToString());
                return;
            }


            */

        }


        public Form1()
        {
            InitializeComponent();
            //backgroundWorker1.RunWorkerAsync(); //lanzamos el hilo de escucha de mensajes
           // getConfig();

            //msg = usahostname ? (" Puesto: " + Dns.GetHostName() + msg) : msg; // hay que añadir el hostname? - lo añadimos
            //msg = usausername ? (" Usuario: " + Environment.UserName + msg) : msg; // hay que añadir el username? - lo añadimos
            //msg = " MENSAJE:" + msg;
            Console.WriteLine("[DEBUG] Mensaje a enviar: " + msg);

            textBox1.Text = msg; //actualizamos el gui
            textBox2.Text = puerto.ToString();
            textBox3.Text = Environment.UserName;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //creamos un socket UDP
            Socket socktx = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint iep1 = new IPEndPoint(IPAddress.Broadcast, int.Parse(textBox2.Text));
            //IPEndPoint iep1 = new IPEndPoint(IPAddress.Broadcast, 9050);

            string msg = textBox1.Text;
            msg = "" + textBox3.Text.ToString() + ":" + msg;
            byte[] data = Encoding.ASCII.GetBytes(msg);


            //mandamos a broadcast, aqui elegimos los parametros del socket
            socktx.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            socktx.SendTo(data, iep1); //mandamos datos, en el socket a iep1, que es la dirección de destino
            socktx.Close(); //cerramos el socket, ya no lo necesitamos
        }


        // Procedimiento a ser ejecutado asíncronamente en un hilo para la recepción de paquetes
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            //inicialización del socket: tipo UDP
            Socket sockrx = new Socket(AddressFamily.InterNetwork,
                  SocketType.Dgram, ProtocolType.Udp);

            //aqui definimos que queremos escuchar paquetes desde cualquier dirección y a que puerto
            IPEndPoint iep = new IPEndPoint(IPAddress.Any, int.Parse(textBox2.Text.ToString()));
            sockrx.Bind(iep); //bindeamos el puerto

            //esto es para alojar los datos del emisor del paquete
            EndPoint ep = (EndPoint)iep;

            Console.WriteLine("Ready to receive...");
            byte[] data = new byte[65535]; //buffer para los datos recibidos

            while (true)
            {

                int recv = sockrx.ReceiveFrom(data, ref ep);

                //aqui hemos recibido un paquete y pasamos el contenido a datos ASCII
                string stringData = Encoding.ASCII.GetString(data, 0, recv);

                Console.WriteLine("received: {0}  from: {1}", stringData, ep.ToString());
                IPEndPoint ipep = (IPEndPoint) ep;

                //MessageBox.Show(IsLocalIpAddress(ipep.Address.ToString()).ToString() + ": " + ipep.Address.ToString(), "Local?");

                //notificamos a la aplicación y le pasamos como parámetro el contenido del paquete
                //if (stringData.StartsWith(" MENSAJE:") & 
                //if(!IsLocalIpAddress(ipep.Address.ToString()) )
                backgroundWorker1.ReportProgress(1, stringData);

                //creamos otro buffer para el siguiente paquete
                data = new byte[65535];

                if (backgroundWorker1.CancellationPending) // Nos han pedido cerrar
            {
                sockrx.Close(); //asi que cerramos el socket
                return; // y salimos del procedimiento
            }

            }

        }

        //procedimiento llamado por el hilo asincrono con los datos recibidos
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

            MessageBox.Show(e.UserState.ToString(), "Mensajero: Mensaje recibido",MessageBoxButtons.OK,MessageBoxIcon.Exclamation,MessageBoxDefaultButton.Button1,MessageBoxOptions.ServiceNotification);
            return;
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e) //contador de caracteres
        {
            label2.Text = textBox1.TextLength.ToString() + "/500 caracteres";
            if (textBox1.TextLength > 500) button1.Enabled = false;
            else button1.Enabled = true;

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form1.ActiveForm.Hide();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            //if (!ocultarGUI) Form1.ActiveForm.Height = 400;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //e.Cancel = true; //No cerrar el programa
            //if (e.CloseReason == CloseReason.WindowsShutDown) e.Cancel = false; //Excepción: cierre de windows

        }

        private void button3_Click(object sender, EventArgs e)
        {
            try{
            if (int.Parse(textBox2.Text.ToString()) > 1024 && int.Parse(textBox2.Text.ToString()) <= 65535)
            {
                //backgroundWorker1
                backgroundWorker1.RunWorkerAsync();
                textBox2.Enabled = false;
                button3.Enabled = false;
                button1.Enabled = true;

            }
            else MessageBox.Show("Puerto no válido, debe estar entre 1025 y 65535", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } catch ( Exception exc) 
            { 
                MessageBox.Show("La has liao parda!", "Excepción!", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
        }
        
        /*
        private void globalEventProvider1_KeyDown(object sender, KeyEventArgs e)
        {
            // Recibida pulsación de tecla, es modificadora?
            if (e.KeyValue == 162) isCtrl = true;
            if (e.KeyValue == 164) isAlt = true;

            // Si ambas teclas modificadoras estan abajo y recibimos una A (control+alt+A), mandamos el mensaje
            if (e.KeyValue == 65 && isCtrl && isAlt)
            {
                button1_Click(null, null); // "Click" al botón de mandar mensaje
                //MessageBox.Show("Sending");
                isAlt = isCtrl = false; // evitar dobles mensajes por aporreo de teclas
            }
        }

        private void globalEventProvider1_KeyUp(object sender, KeyEventArgs e)
        {
            // Se ha levantado una tecla modificadora
            if (e.KeyValue == 162) isCtrl = false;
            if (e.KeyValue == 164) isAlt = false;
        }*/
    }
}
